/*
 * @Author       : Deng
 * @Date         : 2024-05-19 09:15:36
 * @LastEditors  : Joel
 * @LastEditTime : 2024-05-19 17:43:50
 * @FilePath     : \src\linked_list.c
 * @Description  : 
 * Copyright 2024 YiJiaLink, All Rights Reserved. 
 * 2024-05-19 09:15:36
 */
/*
 * @Author: Joel
 * @Date: 2023-07-16 10:34:32
 * @LastEditors: Joel
 * @LastEditTime: 2023-07-19 01:27:26
 * @FilePath: /hc32f460_freertos/usr_app/src/linklist.c
 * @Description: 链表
 * Copyright (c) 2022 by DongGuan City YiJiaLink, All Rights Reserved.
 */

#include "linked_list.h"
/* 测试数据用于检查链表的工作是否正能正常使用 */
uint32_t test_rxbuffer[10] = {0};
/**
 * @description: @description链表测试用于检查链表是否能正常创建与释放
 * @return {*}int
 */
int linklist_test_main(void)
{
    uint8_t i;
    // 初始化链表（1，2，3，4）
    //  printf("初始化链表为：\n");
    link *p = initLink(test_rxbuffer, sizeof(test_rxbuffer)/sizeof(uint32_t));
    display_lenth(p);

    printf("insertElem:5\n");
    p = insertElem(p, 5, 4);
    display_lenth(p);
    printf("insert_list_last:8\n");
    for (i = 0; i < 5; i++)
        p = insert_list_last(p, 8);
    display_lenth(p);
    printf("delElem:3\n");
    p = delElem(p, 3);
    display_lenth(p);

    printf("selectElem:2\n");
    int address = selectElem(p, 2);
    if (address == -1)
    {
        // printf("没有该元素");
    }
    else
    {
        // printf("元素2的位置为：%d\n",address);
    }
    printf("amendElem:3-7\n");
    p = amendElem(p, 3, 7);
    display_lenth(p);

    p = disposal_LinkList(p);
    printf("clean linklist:\n");
    display_lenth(p);
    
    return 0;
}
/**
 * @description: @description在链表的最后插入指定数据
 * @param {link} *head 传入的链表
 * @param {uint8_t} data 需要插入的数据值
 * @return {*} 返回更新后的链表
 */
link *insert_list_last(link *head, uint8_t data)
{
    link *temp = head; // 创建临时结点temp
    if (temp == NULL)
        return head;
    // 只要temp指针指向的结点的next不是Null，就执行输出语句。
    while (temp->next)
    {
        temp = temp->next;
    }
    // 初始化一个新的结点，准备进行链接
    // 创建插入结点c
    link *c = (link *)malloc(sizeof(link));
    c->elem = data;
    // 向链表中插入结点
    c->next = temp->next;
    temp->next = c;
    return head;
}
/**
 * @description: @description初始化构建 1个新动态链表
 * @param {uint32_t} data 传入的数组
 * @param {uint32_t} length 数组长度
 * @return {*} 返回链表
 */
link *initLink(uint32_t data[], uint32_t length)
{
    link *p = (link *)malloc(sizeof(link)); // 创建一个头结点
    link *temp = p;                         // 声明一个指针指向头结点，用于遍历链表
    // 生成链表
    for (int i = 0; i < length; i++)
    {
        link *a = (link *)malloc(sizeof(link));
        a->elem = data[i];
        a->next = NULL;
        temp->next = a;
        temp = temp->next;
    }
    return p;
}

/**
 * @description: @description 在链表中的指定位置插入数据
 * @param {link *} p 传入的链表
 * @param {uint32_t} elem 数据值
 * @param {int} add 链表中的位置
 * @return {*} 更新后的链表
 */
link *insertElem(link *p, uint32_t elem, int add)
{
    link *temp = p; // 创建临时结点temp
    if (temp == NULL)
    {
        // printf("length= %d\n", length);
        return temp;
    }
    // 首先找到要插入位置的上一个结点
    for (int i = 1; i < add; i++)
    {
        if (temp == NULL)
        {
            printf("插入位置无效\n");
            return p;
        }
        temp = temp->next;
    }
    // 创建插入结点c
    link *c = (link *)malloc(sizeof(link));
    c->elem = elem;
    // 向链表中插入结点
    c->next = temp->next;
    temp->next = c;
    return p;
}
/**
 * @description: @description 在链表中指定位置删除1个元素
 * @param {link *} p 传入的链表
 * @param {int} add 链表中元素的位置
 * @return {*} 返回更新后的链表
 */
link *delElem(link *p, int add)
{
    link *temp = p;
    if (temp == NULL)
        return temp;

    // 遍历到被删除结点的上一个结点
    for (int i = 1; i < add; i++)
    {
        temp = temp->next;
    }
    link *del = temp->next;        // 单独设置一个指针指向被删除结点，以防丢失
    temp->next = temp->next->next; // 删除某个结点的方法就是更改前一个结点的指针域
    free(del);                     // 手动释放该结点，防止内存泄漏
    return p;
}
/**
 * @description: @description 查找指元素在链表中的位置
 * @param {link *} p 传入的链表
 * @param {uint8_t} elem 数据值
 * @return {*} 返回数据在链表中的位置
 */
int selectElem(link *p, uint32_t elem)
{
    link *t = p;
    int i = 1;
    if (t == NULL)
        return -1;
    while (t->next)
    {
        t = t->next;
        if (t->elem == elem)
        {
            return i;
        }
        i++;
    }
    return -1;
}
/**
 * @description: @description 更改指定位置链表的数据
 * @param {link *} p 传入的链表
 * @param {int} add 需要更改的位置
 * @param {int} newElem 位置的值
 * @return {*} 返回修改后的值
 */
link *amendElem(link *p, int add, int newElem)
{
    link *temp = p;

    if (temp == NULL)
        // printf("length= %d\n", length);
        return p;
    temp = temp->next; // tamp指向首元结点

    // temp指向被删除结点
    for (int i = 1; i < add; i++)
    {
        temp = temp->next;
    }
    temp->elem = newElem;
    return p;
}
/**
 * @description: @description获取链表长度
 * @param {link} *p 传入需要计算的链表
 * @return {*} 返回链表长度
 */
int display_lenth(link *p)
{
    link *temp = p; // 将temp指针重新指向头结点
    int length = 0;
    // 只要temp指针指向的结点的next不是Null，就执行输出语句。
    if (p == NULL)
    {
        // printf("length= %d\n", length);
        return length;
    }
    while (temp->next)
    {
        length++;
        temp = temp->next;
        // printf("%d", temp->elem);
    }
    // printf("\n");
    printf("length= %d\n", length);
    return length;
}
/**
 * @description: 查找最后一个数据
 * @param {link} *p
 * @return {*}
 */
int display_last_data(link *p)
{
    link *temp = p; // 将temp指针重新指向头结点
    int data = 0;
    // 只要temp指针指向的结点的next不是Null，就执行输出语句。
    if (p == NULL)
    {
        // printf("length= %d\n", length);
        return data;
    }
    while (temp->next)
    {

        temp = temp->next;
        data = temp->elem;
        // printf("%d", temp->elem);
    }
    // printf("\n");
    // printf("length= %d\n", length);
    return data;
}
/**
 * @description: @description 销毁链表
 * @param {link} *headNode 传入需要销毁的链表
 * @return {*} 返回空链表
 */
link *disposal_LinkList(link *headNode)
{
   if (headNode == NULL)
        return headNode;

    // 清空链表,是不清空头节点的，因此从第一个有数据的节点开始释放
    NodeList curNode = headNode->next;
    while (curNode != NULL)
    {
        // 先保住下一个节点的位置
        NodeList nextNode = curNode->next;
        free(curNode);
        curNode = nextNode;
    }
    // 释放头结点
    free(headNode);
    // 头结点指针置空
    headNode = NULL;
    return headNode;
}
/**
 * @description: 链表数据转为数组
 * @return {*}
 */
uint32_t list_conver_to_arr(link *node, uint32_t data_arr[], uint16_t length)
{
    static uint16_t number;
    number = 0;
    link *p = node;
    if (node != NULL)
        p = p->next;
    else
        return number;
    // 遍历头节点到，最后一个数据
    while (p != NULL)
    {

        data_arr[number] = p->elem;
        p = p->next;

        if (length <= ++number)
        {
            node = p;
            return number;
        }
    }
    node = p;
    return number;
}